package com.dyh.quickdemozwei;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;

@Slf4j
public class TestNoLockListComplete {

    ThreadPoolExecutor poolExecutor;
    {
        this.poolExecutor = new ThreadPoolExecutor(3,6,
                300, TimeUnit.SECONDS,
//                new SynchronousQueue<>(),
                new LinkedBlockingQueue<>(200),
                new ThreadFactoryBuilder().setNameFormat("pool-%d").build(),
                new ThreadPoolExecutor.CallerRunsPolicy()
        );
    }


    class LongArrayTag{

        long [] zone;


        public LongArrayTag(int size){
            int row  = size/64;
            zone = new long[row+1];//整除的也暂时多一个
        }

        public void mark(int index){
            int row = index/64;
            int col = index%64;


        }
    }



//    @Test public void test(){
//
////        LongArrayTag longArrayTag = new LongArrayTag(67);
//
//        System.out.println();
//    }

    Random random = new Random(11);
    @Test
    public void test(){
        List<Integer> datas = Lists.newArrayList(1,2,3,4,5);

//        List<Byte> tags = new ArrayList<>(datas.size());

        byte[] tags = new byte[datas.size()];

        List<Future> futures = new ArrayList<>();

        for (int i = 0;i<datas.size();i++){
            int d = datas.get(i);

            int finalI = i;
            futures.add( poolExecutor.submit(()->{
                consumer.accept(d);
                tags[finalI]=1;
            }));

        }

        Runnable timeWait = ()->{

            l1:
            for (;;){
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                /*倒序减少for循环*/

                for (int i=tags.length-1;i>=0;i--){
                    if (tags[i]==0)
                        continue l1;
                }

                break;
            }

        };


        Thread waitThread = new Thread(timeWait::run);
        waitThread.setName("waitThread");
        waitThread.start();

        try {
            waitThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

//        cpuWait.run();

        //倒序更好？
//        futures.forEach(e-> {
//            try {
//                e.get();
//               printBytes(tags);
//            } catch (InterruptedException e1) {
//                e1.printStackTrace();
//            } catch (ExecutionException e1) {
//                e1.printStackTrace();
//            }
//        });


        printBytes(tags);


    }

    @Test
    public void test2(){
        long startTime = System.currentTimeMillis();
        List<Integer> datas = Lists.newArrayList(1,2,3,4,5);


        byte[] tags = new byte[datas.size()];

        List<Future> futures = new ArrayList<>();

        for (int i = 0;i<datas.size();i++){
            int d = datas.get(i);

            int finalI = i;
            futures.add( poolExecutor.submit(()->{
                consumer.accept(d);
                tags[finalI]=1;
            }));

        }

        Runnable timeWait = ()->{

            l1:
            for (;;){
                try {
                    Thread.sleep(50L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                /*倒序减少for循环*/
//                printBytes(tags);
                for (int i=tags.length-1;i>=0;i--){
                    if (tags[i]==0)
                        continue l1;
                }

                break;
            }

        };
        Runnable cpuWait = ()->{

            l1:
            for (;;){
                try {
                    Thread.sleep(50L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                /*倒序减少for循环*/
//                printBytes(tags);
                for (int i=tags.length-1;i>=0;i--){
                    if (tags[i]==0)
                        continue l1;
                }

                break;
            }

        };

//        timeWait.run();
//        cpuWait.run();

        Thread waitThread = new Thread(timeWait);
        waitThread.setName("waitThread");
        waitThread.start();

        //倒序更好？
//        futures.forEach(e-> {
//            try {
//                e.get();
//               printBytes(tags);
//            } catch (InterruptedException e1) {
//                e1.printStackTrace();
//            } catch (ExecutionException e1) {
//                e1.printStackTrace();
//            }
//        });


        try {
            waitThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        long endTime = System.currentTimeMillis();

        log.info("diff-time {}",endTime-startTime);
        printBytes(tags);


    }

    public void printBytes(byte[] bytes){
        StringBuilder sb = new StringBuilder();

        for (byte aByte : bytes) {
            sb.append(aByte).append(",");
        }

        sb.insert(0,"[");
        sb.replace(sb.length()-1,sb.length(),"]");
        log.info(sb.toString());
    }

    Consumer<Integer> consumer = e->{
        log.info("{} 开始消费-{}",Thread.currentThread().getName(),e);
        try {
            int rTime =  random.nextInt(4);
            Thread.sleep(1000L+rTime*70L);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        log.info("{} 结束消费-{}",Thread.currentThread().getName(),e);
    };

    class  WorkThread extends Thread{
       @Override
       public void run() {

       }
   }

   class ManagerThread extends Thread{

       @Override
       public void run() {

       }


   }

   class Manager{
        LinkedBlockingQueue<Integer> taskQueue = new LinkedBlockingQueue<>(4);
        AtomicLong seqno = new AtomicLong(0);
        public void apply(List<Integer> tasks){
            seqno.getAndIncrement();

        }
   }


}
